package com.pokermind.common.log;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 手牌操作专用日志记录器 提供德州扑克业务统一的日志格式和内容
 *
 * @author PokerMind Team
 */
public class HandOperationLogger {

    private final Logger logger;
    private final PlainLog operationLog;

    private HandOperationLogger(String operation, Object... keyValues) {
        this.logger = LoggerFactory.getLogger(HandOperationLogger.class);
        this.operationLog = new TimeCostLog("api", operation);
        // 设置初始键值对
        for (int i = 0; i < keyValues.length - 1; i += 2) {
            if (keyValues[i] != null && keyValues[i + 1] != null) {
                operationLog.put(keyValues[i].toString(), keyValues[i + 1]);
            }
        }
    }

    // === 静态工厂方法 ===

    /**
     * 创建手牌创建操作日志 (传统方式)
     */
    public static HandOperationLogger forCreateHand(String handId, String tableId, Integer buttonSeat) {
        return new HandOperationLogger("createHand", "handId", handId, "tableId", tableId, "buttonSeat", buttonSeat);
    }

    /**
     * 创建手牌创建操作日志 (从请求对象 - 一步到位)
     */
    public static HandOperationLogger forCreateHand(Object request) {
        HandOperationLogger logger = new HandOperationLogger("createHand");

        if (request != null) {
            try {
                Class<?> requestClass = request.getClass();

                // 提取基础信息
                try {
                    java.lang.reflect.Method getHandId = requestClass.getMethod("getHandId");
                    logger.with("handId", getHandId.invoke(request));
                } catch (Exception ignored) {
                }

                try {
                    java.lang.reflect.Method getTableId = requestClass.getMethod("getTableId");
                    logger.with("tableId", getTableId.invoke(request));
                } catch (Exception ignored) {
                }

                try {
                    java.lang.reflect.Method getButtonSeat = requestClass.getMethod("getButtonSeat");
                    logger.with("buttonSeat", getButtonSeat.invoke(request));
                } catch (Exception ignored) {
                }

                // 提取详细信息 (相当于 withRequestInfo 的功能)
                try {
                    java.lang.reflect.Method getPlayers = requestClass.getMethod("getPlayers");
                    Object players = getPlayers.invoke(request);
                    if (players instanceof java.util.List) {
                        logger.with("playersCount", ((java.util.List<?>)players).size());
                    }
                } catch (Exception ignored) {
                }

                try {
                    java.lang.reflect.Method getSmallBlind = requestClass.getMethod("getSmallBlind");
                    logger.with("smallBlind", getSmallBlind.invoke(request));
                } catch (Exception ignored) {
                }

                try {
                    java.lang.reflect.Method getBigBlind = requestClass.getMethod("getBigBlind");
                    logger.with("bigBlind", getBigBlind.invoke(request));
                } catch (Exception ignored) {
                }

                try {
                    java.lang.reflect.Method getAnte = requestClass.getMethod("getAnte");
                    logger.with("ante", getAnte.invoke(request));
                } catch (Exception ignored) {
                }

            } catch (Exception e) {
                logger.with("extractionError", e.getMessage());
            }
        }

        return logger;
    }

    /**
     * 创建Hero底牌更新操作日志
     */
    public static HandOperationLogger forUpdateHeroCards(Long handRecordId) {
        return new HandOperationLogger("updateHeroCards", "handRecordId", handRecordId);
    }

    /**
     * 创建街道转换操作日志
     */
    public static HandOperationLogger forStreetTransition(Long handRecordId, String street) {
        return new HandOperationLogger("streetTransition", "handRecordId", handRecordId, "targetStreet", street);
    }

    /**
     * 创建行动记录操作日志
     */
    public static HandOperationLogger forRecordAction(Long handRecordId, String actionType) {
        return new HandOperationLogger("recordAction", "handRecordId", handRecordId, "actionType", actionType);
    }

    /**
     * 创建手牌完成操作日志
     */
    public static HandOperationLogger forHandCompletion(Long handRecordId, String completionType) {
        return new HandOperationLogger("completeHand", "handRecordId", handRecordId, "completionType", completionType);
    }

    /**
     * 创建通用操作日志
     */
    public static HandOperationLogger forOperation(String operation) {
        return new HandOperationLogger(operation);
    }

    // === 日志记录方法 ===

    /**
     * 添加额外的日志信息
     */
    public HandOperationLogger with(String key, Object value) {
        if (key != null && value != null) {
            operationLog.put(key, value);
        }
        return this;
    }

    /**
     * 添加玩家相关信息 (传统方式)
     */
    public HandOperationLogger withPlayerInfo(Integer playersCount, Object smallBlind, Object bigBlind, Object ante) {
        return this.with("playersCount", playersCount).with("smallBlind", smallBlind).with("bigBlind", bigBlind)
            .with("ante", ante);
    }

    /**
     * 添加玩家相关信息 (从CreateHandRequest)
     */
    public HandOperationLogger withPlayerInfo(java.util.List<?> players, Object smallBlind, Object bigBlind,
        Object ante) {
        return this.with("playersCount", players != null ? players.size() : 0).with("smallBlind", smallBlind)
            .with("bigBlind", bigBlind).with("ante", ante);
    }

    /**
     * 从完整请求对象中添加信息 (最简洁方式) 使用反射获取常用字段，避免循环依赖
     */
    public HandOperationLogger withRequestInfo(Object request) {
        if (request == null) {
            return this;
        }

        try {
            // 通过反射获取常用字段，避免循环依赖
            Class<?> requestClass = request.getClass();

            // 获取 players 列表
            try {
                java.lang.reflect.Method getPlayers = requestClass.getMethod("getPlayers");
                Object players = getPlayers.invoke(request);
                if (players instanceof java.util.List) {
                    this.with("playersCount", ((java.util.List<?>)players).size());
                }
            } catch (Exception ignored) {
            }

            // 获取盲注信息
            try {
                java.lang.reflect.Method getSmallBlind = requestClass.getMethod("getSmallBlind");
                this.with("smallBlind", getSmallBlind.invoke(request));
            } catch (Exception ignored) {
            }

            try {
                java.lang.reflect.Method getBigBlind = requestClass.getMethod("getBigBlind");
                this.with("bigBlind", getBigBlind.invoke(request));
            } catch (Exception ignored) {
            }

            try {
                java.lang.reflect.Method getAnte = requestClass.getMethod("getAnte");
                this.with("ante", getAnte.invoke(request));
            } catch (Exception ignored) {
            }

        } catch (Exception e) {
            // 反射失败时静默处理，不影响日志记录
            this.with("requestInfoError", e.getMessage());
        }

        return this;
    }

    /**
     * 添加响应信息
     */
    public HandOperationLogger withResponse(Object handRecordId) {
        return this.with("handRecordId", handRecordId);
    }

    /**
     * 记录成功日志
     */
    public void logSuccess() {
        operationLog.put("op_rslt", "success");
        logger.info(operationLog.toString());
    }

    /**
     * 记录成功日志（带消息）
     */
    public void logSuccess(String message) {
        operationLog.put("op_rslt", "success").put("message", message);
        logger.info(operationLog.toString());
    }

    /**
     * 记录参数验证错误
     */
    public void logValidationError(String errorMessage) {
        operationLog.put("op_rslt", "validation_error").put("error", errorMessage);
        logger.warn(operationLog.toString());
    }

    /**
     * 记录业务异常
     */
    public void logBusinessError(String errorCode, String errorMessage) {
        operationLog.put("op_rslt", "business_error").put("errorCode", errorCode).put("error", errorMessage);
        logger.warn(operationLog.toString());
    }

    /**
     * 记录系统异常
     */
    public void logSystemError(String errorMessage, Throwable cause) {
        operationLog.put("op_rslt", "system_error").put("error", errorMessage);
        logger.error(operationLog.toString(), cause);
    }

    /**
     * 记录未预期的异常
     */
    public void logUnexpectedError(Exception ex) {
        operationLog.put("op_rslt", "unexpected_error").put("errorType", ex.getClass().getSimpleName())
            .put("error", ex.getMessage());
        logger.error(operationLog.toString(), ex);
    }

    /**
     * 获取原始日志对象（用于特殊情况）
     */
    public PlainLog getRawLog() {
        return operationLog;
    }
}
